package com.cloud.quickconfigure.swagger;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Configuration
@EnableSwagger2
@Profile({"dev"})
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerAutoConfiguration implements BeanFactoryAware {

    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(@NonNull BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Bean
    public List<Docket> docket(SwaggerProperties properties) {
        ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) this.beanFactory;

        List<Docket> dockets = new ArrayList<>();
        if (StringUtils.hasText(properties.getGroupName()) && StringUtils.hasText(properties.getBasePackage())) {
            this.doIt(dockets, beanFactory, properties.getGroupName(), properties.getBasePackage());
        }
        if (!CollectionUtils.isEmpty(properties.getInfos())) {
            properties.getInfos().stream().sorted(Comparator.comparing(SwaggerProperties.Info::getOrder))
                    .forEach(i -> doIt(dockets, beanFactory, i.getGroupName(), i.getBasePackage()));
        }
        return dockets;
    }

    private ApiInfo apiInfo() {
        return ApiInfo.DEFAULT;
    }

    private void doIt(List<Docket> dockets, ConfigurableBeanFactory beanFactory, String groupName,
                      String basePackage) {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName(groupName)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage(basePackage))
                .paths(PathSelectors.any())
                .build();
        dockets.add(docket);
        beanFactory.registerSingleton(groupName, docket);
    }
}
